﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Globalization;

namespace Reg_to_head_Cmdline {
	internal class reg {
		public int Line_num;
		public string original;
		public string name;
		public string desc;
		public string str_address;
		public int address;
		public (string name, int len)[] bit_define = new (string name, int len)[8];
		public string warning = "";
		public bool bit_paresed = false;
		public bool byte_paresed = false;
		public bool is_xreg;

		public bool paresed = false;

		public reg(string original,int line_num = -1) {
			this.original = original;
			this.Line_num = line_num;
		}

		static readonly char[] write_space = new char[] { ' ', '\t' };
		public void Parse() {
			if (paresed) {
				throw new InvalidOperationException("每个寄存器只能转换一次。");
			}
			paresed = true;
			//找到地址
			var addr_matchs = Regex.Matches(original, @" [0-9A-F]{2}H ");
			//获取地址
			if (addr_matchs.Count == 1) {
				is_xreg = false;
				str_address = addr_matchs[0].Value.Substring(1, 2);
			} else {
				addr_matchs = Regex.Matches(original, @" [0-9A-F]{4}H ");
				if (addr_matchs.Count == 1) {
					is_xreg = true;
					str_address = addr_matchs[0].Value.Substring(1, 4);
				} else {
					warning += $"【错误】这一行没有找到唯一的地址，（形如 80H 或者 FB4AH ）";
					return;
				}
			}
			
			if (false == int.TryParse(str_address, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address)) {
				warning += $"【错误】没能将地址{str_address}转换为数字";
				return;
			}

			//根据地址分为前部和后部
			string head = original.Substring(0, addr_matchs[0].Index).Trim();
			string tail = original.Substring(addr_matchs[0].Index + addr_matchs[0].Length).Trim();

			//从前部提取描述和寄存器名字
			var head_ss = head.Split(write_space, 2);
			name = head_ss[0].Replace('/','_');
			desc = head_ss[1];
			byte_paresed = true;

			//从后部处理寄存器长度中插入空格的问题
			MatchCollection range_matchs = Regex.Matches(tail, @"[ ]*\[[ ]*\d+[ ]*:[ ]*\d+[ ]*\]");
			if (range_matchs.Count != 0) {
				foreach (Match m in range_matchs) {
					tail = tail.Replace(m.Value, m.Value.Replace(" ", ""));
				}
			}

			//将后部的最后，也就是初值表取出填入描述
			var init_value_matchs = Regex.Matches(tail, @"[10nx]{4},[10nx]{4}");
			if (init_value_matchs.Count != 1) {
				warning += $"【警告】没能找到形如 x000,xxx0 的初始值表";
				return;
			}
			desc += $"，初始值为{init_value_matchs[0].Value.Trim()}";

			if (init_value_matchs[0].Index == 0) {
				return;
			}



			//将后部拆分为多个寄存器描述
			var tail_ss = tail.Substring(0, init_value_matchs[0].Index).Split(write_space, StringSplitOptions.RemoveEmptyEntries);
			int i = 7;
			foreach (var bit_str in tail_ss) {
				var r_mch = Regex.Matches(bit_str, @"\[\d+:\d+]");
				int bf_length = 1;
				if (r_mch.Count == 1) {
					int bgn, end;
					if (!int.TryParse(Regex.Match(r_mch[0].Value, @"\[\d+").Value.Substring(1), out bgn)) {
						warning += $"位域宽度起始值错误。";
						return;
					}
					if (!int.TryParse(Regex.Match(r_mch[0].Value, @":\d+").Value.Substring(1), out end)) {
						warning += $"位域宽度截止值错误。";
						return;
					}
					bf_length = (bgn - end) + 1;
					i = i - (bgn - end);
				} else if (r_mch.Count > 1) {
					warning += $"找到了多余1个位定义长度信息。";
					return;
				}

				if (i < 0) {
					warning += $"处理位定义时，位定位小于0。";
					return;
				}

				if (r_mch.Count == 0) {
					bit_define[i] = (bit_str.Trim().Replace('/', '_'), bf_length);
				} else {
					bit_define[i] = (bit_str.Substring(0, r_mch[0].Index).Trim().Replace('/', '_'), bf_length);
				}
				i--;
			}
			if (i != -1) {
				warning += $"处理完成位定义后，没有填满所有的位定义空间。";
				return;
			}
			bit_paresed = true;



			return;
		}

		public void Report() {
			Console.ForegroundColor = ConsoleColor.Cyan;
			Console.WriteLine($"第{Line_num}行：\t{original}");

			if (byte_paresed == false) {
				if (warning != "") {
					Console.ForegroundColor = ConsoleColor.Red;
					Console.WriteLine($"\t{warning}");
				}
				goto end;
			}
			Console.ForegroundColor = ConsoleColor.White;
			Console.WriteLine($"寄存器：{name} 地址：{address:x}\t\t//{desc}");

			if (warning != "") {
				Console.ForegroundColor= ConsoleColor.Yellow;
				Console.WriteLine($"\t{warning}");
			}
			if (bit_paresed) {
				Console.ForegroundColor = ConsoleColor.White;
				foreach (var bv in bit_define) {
					if (bv.name == null) {
						Console.Write(" ");
					} else if (bv.name == "-") {
						Console.Write("- ");
					} else {
						Console.Write($"{bv.name}:{bv.len} ");
					}
				}
				Console.WriteLine($"");
			}
			end:
			Console.WriteLine($"\n");
			return;
		}
		//pad_right_value
		int prv = 10;

		string toBitDef(string name, int len, int i) {
			//return $"    BIT_DIFF({bd.name.PadRight(prv, ' ')}, {i}  ,{bd.len})";
			return $"SFR_BIT_DIFF( {name.PadRight(prv, ' ')},{i})\n";
		}
		string toSFR() {
			return $"SFR({name.PadRight(prv, ' ')},0x{address:X2})\n";
		}
		string toXSFR() {
			return $"XSFR({name.PadRight(prv, ' ')},0x{address:X4})\n";
		}


		public void toIarDef(StringBuilder  sb, Dictionary<string, string> symbols) {
			sb.AppendLine($"//第{Line_num}行：\t{original}");
			if (byte_paresed == false) {
				if (warning != "") {
					sb.AppendLine($"//识别失败：{warning}");
				}
				goto end;
			}
			sb.AppendLine($"//{desc}");

			void addName(string name,string line,bool focus = false) {
				if (focus==false) {
					if (symbols.Keys.Contains(name)) {
						if (symbols[name] == line) {//新加的语句和已有的相同，不添加
							return;
						}else {//新加的语句和已有的不相同，添加并警告
							sb.Append("//warning 这个符号重复了，但是值不同："); 
							sb.Append(line);
							sb.Append('\n');
							return;
						}
					}
				}
				symbols.Add(name, line);
				sb.Append(line);
			}

			if (is_xreg == false) {
				if ((address % 8) == 0) {
					if (bit_paresed) {
						addName(name, $"  SFRBIT({name.PadRight(prv, ' ')},0x{address:X2}  ",true);
						for (int i = 0; i < 8; i++) {
							var bd = bit_define[i];
							if ((bd.name != null) && (bd.name != "-") && (bd.name != "1") && (bd.name != "0")) {
								addName(bd.name, $",{bd.name.PadRight(prv, ' ')}", true);
							} else {
								string temp_name = $"{name}_{i}";
								addName(temp_name,$",{temp_name.PadRight(prv, ' ')}", true);
							}
						}
						sb.Append($"  )\n");
						for (int i = 0; i < 8; i++) {
							(string name, int len) bd = bit_define[i];
							if ((bd.name != null) && (bd.name != "-") && (bd.name != "1") && (bd.name != "0")) {
								string temp_name = $"_{bd.name}";
								addName(temp_name, toBitDef(temp_name, bd.len, i));
							}
						}
					} else {
						addName(name, toSFR(), true);
					}

				} else {
					addName(name, toSFR(), true);
					if (bit_paresed) {
						for (int i = 0; i < 8; i++) {
							(string name, int len) bd = bit_define[i];
							if ((bd.name != null) && (bd.name != "-") && (bd.name != "1") && (bd.name != "0")) {
								addName(bd.name, toBitDef(bd.name, bd.len, i));
							}
						}
					}
				}
			} else {
				addName(name, toXSFR());
				if (bit_paresed) {
					for (int i = 0; i < 8; i++) {
						var bd = bit_define[i];
						if ((bd.name != null) && (bd.name != "-") && (bd.name != "1") && (bd.name != "0")) {
							if ((bd.name != null) && (bd.name != "-") && (bd.name != "1") && (bd.name != "0")) {
								addName(bd.name, toBitDef(bd.name, bd.len, i));
							}
						}
					}
				}
			}
		end:
			sb.AppendLine();
			return;
		}

	}
}
